package com.rockwell.sniffyhunter.model;

import java.util.ArrayList;

import com.rockwell.sniffyhunter.utils.IMazeSolver;
import com.rockwell.sniffyhunter.utils.IRobotLogger;

public class PredefinedMazeSolver implements IMazeSolver {
	private ArrayList<RobotAction> m_actions;
	
	private IMazeSolver m_fallbackSolver;
	
	private IRobotLogger m_logger;
	
	private int m_index = 0;
	
	private boolean m_hasError = false;
	
	private RobotCommand m_com = new RobotCommand();
	
	public PredefinedMazeSolver(ArrayList<RobotAction> directions, 
			IMazeSolver fallbackSolver, IRobotLogger logger) {
		// assert(m_intersections.length == m_directions.length)
		
		m_actions = directions;
		m_fallbackSolver = fallbackSolver;
		m_logger = logger;
	}
	
	@Override
	public RobotCommand nextAction(RobotPosition rp, boolean needToDetectFrontWall) {
		if (m_hasError) {
			return m_fallbackSolver.nextAction(rp, needToDetectFrontWall);
		}

		RobotAction ra = m_actions.get(m_index);
		
		switch (rp.junctionLocation)
		{
		case LaneLeft2:
		case LaneLeft1:
		case LaneRight2:
		case LaneRight1:
		case LaneCenter:
			m_com.action = RobotAction.Jog;
			break;
			
		case RightTurnOnlyButTooLeft2:
		case RightTurnOnlyButTooLeft1:
		case RightTurnOnly:
			if (needToDetectFrontWall) {
				m_com.action = RobotAction.Detect_Front_Wall;
			}
			else {
				if (ra == RobotAction.TurnRight)
					m_com.action = RobotAction.TurnRight;
				else
					hasError(true);
			}
			break;
			
		case TRightStraightButTooLeft2:
		case TRightStraightButTooLeft1:
		case TRightStraight:
			if (needToDetectFrontWall) {
				m_com.action = RobotAction.Detect_Front_Wall;
			}
			else {
				if (ra == RobotAction.TurnRight || ra == RobotAction.Jog) 
					m_com.action = ra;
				else
					hasError(true);
			}
			break;
			
		case LeftTurnOnlyButTooRight2:
		case LeftTurnOnlyButTooRight1:
		case LeftTurnOnly:
			if (ra == RobotAction.TurnLeft)
				m_com.action = RobotAction.TurnLeft;
			else
				hasError(true);
			break;
			
		case TLeftStraightButTooRight2:
		case TLeftRStraightButTooRight1:
		case TLeftStraight:
			if (needToDetectFrontWall) {
				m_com.action = RobotAction.Detect_Front_Wall;
			}
			else {
				if (ra == RobotAction.TurnLeft || ra == RobotAction.Jog) 
					m_com.action = ra;
				else
					hasError(true);
			}
			break;
			
		case TLeftRight:
			if (ra == RobotAction.TurnLeft || ra == RobotAction.TurnRight) 
				m_com.action = ra;
			else
				hasError(true);
			break;
			
		case FourWay:
			if (needToDetectFrontWall) {
				m_com.action = RobotAction.Detect_Front_Wall; 
			}
			else {
				m_com.action = m_actions.get(m_index);
			}
			break;
			
		case DeadEnd:
			if (ra == RobotAction.TurnBack)
				m_com.action = RobotAction.TurnBack;
			else
				hasError(true);
			break;
			
		default:
			assert(false);
			break;
		}
		
		if (m_hasError)
			return m_fallbackSolver.nextAction(rp, needToDetectFrontWall);
		else
			return m_com;
	}

	@Override
	public void onJunctionPassed(RobotAction action) {
		m_index++;
		/*
		if (junction == m_intersections.get(m_index)) {
			m_index++;
		}
		else {
			m_hasError = true;
		}
		*/
	}

	private void hasError(boolean hasError) {
		if (!m_hasError && hasError && m_logger != null) {
			m_logger.log("Predefine solver failed");
		}
		
		m_hasError = hasError;
	}

	@Override
	public void initialize() {
		m_fallbackSolver.initialize();
	}

	@Override
	public void addSolver(IMazeSolver nestedSolver) {
		// TODO Auto-generated method stub
		
	}
}
